#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/sched/signal.h>
#include <linux/signal.h>
#include <linux/cred.h> // 包含 cred 结构体

#define DEVICE_NAME "sigqueue_dev"
#define CLASS_NAME "sigqueue_class"

static dev_t dev = 0;
static struct cdev c_dev;
static struct class *cl = NULL;

static int major = 0;
static int minor = 0;

static int device_open(struct inode *inode, struct file *file) {
    return 0;
}

static int device_release(struct inode *inode, struct file *file) {
    return 0;
}

static ssize_t device_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) {
    return 0;
}

static ssize_t device_write(struct file *filp, const char __user *buf, size_t count, loff_t *offset) {
    return count;
}

static long device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {
    struct task_struct *task;
    struct kernel_siginfo si;
    union sigval sv;

    task = current; // 获取当前任务
    if (!task) {
        pr_err("get_current failed\n");
        return -EINVAL;
    }

    si.si_signo = SIGUSR1;
    si.si_code = SI_QUEUE;
    si.si_pid = task->pid;
    si.si_uid = current_uid().val; // 使用 current_uid() 获取用户ID

    sv.sival_int = 512; // 发送的数据

    // 使用 send_sig_info 发送信号
    si.si_value = sv;

    send_sig_info(SIGUSR1, &si, task);

    pr_info("Signal sent to PID %d\n", task->pid);
    return 0;
}

static const struct file_operations fops = {
    .open = device_open,
    .release = device_release,
    .read = device_read,
    .write = device_write,
    .unlocked_ioctl = device_ioctl,
};

static int __init sigqueue_dev_init(void) {
    if (alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME) < 0) {
        pr_err("alloc_chrdev_region failed\n");
        return -1;
    }

    major = MAJOR(dev);
    minor = MINOR(dev);

    cdev_init(&c_dev, &fops);

    if (cdev_add(&c_dev, dev, 1) < 0) {
        pr_err("cdev_add failed\n");
        goto fail_cdev_add;
    }

    if ((cl = class_create(THIS_MODULE, CLASS_NAME)) == NULL) {
        pr_err("class_create failed\n");
        goto fail_class_create;
    }

    if (device_create(cl, NULL, dev, NULL, DEVICE_NAME) == NULL) {
        pr_err("device_create failed\n");
        goto fail_device_create;
    }

    pr_info("sigqueue_dev loaded successfully\n");
    return 0;

fail_device_create:
    class_destroy(cl);
fail_class_create:
    cdev_del(&c_dev);
fail_cdev_add:
    unregister_chrdev_region(dev, 1);
    return -1;
}

static void __exit sigqueue_dev_exit(void) {
    device_destroy(cl, dev);
    class_destroy(cl);
    cdev_del(&c_dev);
    unregister_chrdev_region(dev, 1);
    pr_info("sigqueue_dev unloaded successfully\n");
}

module_init(sigqueue_dev_init);
module_exit(sigqueue_dev_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple character device driver that sends signals with data");
